﻿using Bettzueche.RLLibrary.Types;
using Bettzueche.RLLibrary.Util;
using System;

namespace Bettzueche.RLLibrary.Functions {
    /// <summary>
    /// E-'Funktion', die zu jedem (s,a)-Tupel den 'Berechtigungsfaktor' (eligibility) gibt.<para>
    /// Zugriff über einen Indexer.</para>
    /// </summary>
    /// <remarks>Eine Implementierung ist üblicherweise irgendeine Art von Collection.</remarks>
    public interface IEligibilityFunction {

        /// <summary>
        /// Gets or sets the <see cref="System.Double"/> eligibility value with the specified state, action.
        /// </summary>
        double this[IAction action, IState state] { get; set; }

        ///// <summary>
        ///// Gets or sets the eligibility values.
        ///// </summary>
        ///// <value>
        ///// The eligibilities.
        ///// </value>
        //Matrix Eligibilities { get; set; }

        /// <summary>
        /// Gets or sets the discount factor ('gamma').
        /// (Optional. Eventually used by Update method)
        /// </summary>
        /// <value>
        /// The discount factor.
        /// </value>
        double DiscountFactor { get; set; }

        /// <summary>
        /// Gets or sets the trace decay ('lambda').
        /// <para>(Optional. Eventually used by Update method)</para>
        /// </summary>
        /// <value>
        /// The trace decay.
        /// </value>
        double TraceDecay { get; set; }

        /// <summary>
        /// <c>MinE</c> gibt den kleinsten Wert für
        /// 'eligibility' an, der nicht zu 0.0 interpretiert wird. Standard = 0.0.
        /// </summary>
        /// <value>
        /// Der minimale Verantwortlichkeitsfaktor e. Negative Werte werden auf 0.0 gesetzt.
        /// </value>
        double MinE {
            get;
            set;
        }

        /// <summary>
        /// Löscht alle Einträge, bzw. setzt sie auf einen Standardwert zurück.
        /// </summary>
        void Clear();

        /// <summary>
        /// Updates the eligibility function with respect to given state-action pair.
        /// </summary>
        /// <param name="action">The action.</param>
        /// <param name="state">The state.</param>
        /// <returns>This updated <see cref="IEligibilityFunction"/></returns>
        IEligibilityFunction Update(IAction action, IState state);

        ///// <summary>
        ///// Updates the eligibilities depending on the specified actual state and action.<para>
        ///// Optional!</para>
        ///// </summary>
        ///// <param name="lastState">The actual state.</param>
        ///// <param name="lastAction">The actual action.</param>
        //void Update(IState lastState, IAction lastAction);
    }




    /// <summary>
    /// E-'Funktion', die zu jedem (s,a)-Tupel den 'Berechtigungsfaktor' (eligibility) gibt.<para>
    /// Zugriff über einen Indexer.</para>
    /// </summary>
    /// <typeparam name="A">action Type of IAction</typeparam>
    /// <typeparam name="S">state Type of IState</typeparam>
    /// <remarks>
    /// <para>
    /// Eine Implementierung ist üblicherweise irgendeine Art von Collection.
    /// </para><para>
    /// Die optionale Eigenschaft <c>Path</c> kann zur Optimierung von Aktualisierungen dienen, indem
    /// dort die sa-Tupel gespeichert werden, deren e-Wert nicht 0 ist. Nur diese Werte brauchen dann in der Q- oder
    /// E-Funktion aktualisert werden.
    /// </para>
    /// </remarks>
    public interface IEligibilityFunction<A,S> : IEligibilityFunction
        where A : IAction
        where S : IState
    {

        /// <summary>
        /// Gets or sets the <see cref="System.Double"/> eligibility value with the specified state, action.
        /// </summary>
        double this[A action, S state] { get; set; }

        /// <summary>
        /// Gets or sets the path.
        /// Optional. Used for performance optimisation.
        /// </summary>
        /// <value>
        /// The path.
        /// </value>
        TraceSet<SATupel<S, A>> Path { get; /*protected set;*/ }

        /// <summary>
        /// Updates the eligibility function with respect to given state-action pair.
        /// </summary>
        /// <param name="action">The action.</param>
        /// <param name="state">The state.</param>
        /// <returns>This updated <see cref="IEligibilityFunction"/></returns>
        IEligibilityFunction<A,S> Update(A action, S state);

        // Note: Update-InterfaceMethode scheint unpraktikabel zu sein.

        ///// <summary>
        ///// Updates the eligibilities depending on the specified actual state and action.<para>
        ///// Optional!</para>
        ///// </summary>
        ///// <param name="lastState">The actual state.</param>
        ///// <param name="lastAction">The actual action.</param>
        //void Update(S lastState, A lastAction);
    }

}
